#include <jni.h>
#include <string>
#include <stddef.h>
#include  "libmp3lame/lame.h"
#include "mytest/Test.h"

#include <android/log.h>

#define LOG_TAG "System.out"
#define LOG_I(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)


extern "C" JNIEXPORT jstring JNICALL
Java_com_yc_lame_MainActivity_stringFromJNI(JNIEnv *env, jobject /* this */) {
    Test test;

    std::string hello = "别报错了啊啊啊！！";
    hello += test.Area();
    return env->NewStringUTF(hello.c_str());

}
extern "C" JNIEXPORT char *JNICALL
JstringToChar(JNIEnv *env, jstring jstr) {
    char *rtn = NULL;
    jclass clsstring = env->FindClass("java/lang/String");
    jstring strencode = env->NewStringUTF("GB2312");
    jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
    jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid,
                                                         strencode); // String .getByte("GB2312");
    jsize alen = env->GetArrayLength(barr);
    jbyte *ba = env->GetByteArrayElements(barr, JNI_FALSE);
    if (alen > 0) {
        rtn = (char *) malloc(alen + 1); //"\0"
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    env->ReleaseByteArrayElements(barr, ba, 0); //
    return rtn;
}


extern "C" JNIEXPORT void JNICALL
Java_com_yc_lame_LameUtil_test(JNIEnv *env, jclass obj, jstring jwav, jstring jmp3) {
    jboolean isCopy;
    char *cwav = JstringToChar(env, jwav);
    char *cmp3 = JstringToChar(env, jmp3);
    LOG_I("wav = %s", cwav);
    LOG_I("mp3 = %s", cmp3);

    //打开 wav,MP3文件
    FILE *fwav = fopen(cwav, "rb");
    FILE *fmp3 = fopen(cmp3, "wb+");

    short int wav_buffer[8192 * 2];
    //mp3的buffer：官方规定了计算公式：7200 + (1.25 * buffer_l.length)（可以在lame.h文件中看到）
    unsigned char mp3_buffer[8192];

    //初始化lame的编码器
    lame_t lame = lame_init();
    //设置lame mp3编码的采样率
    lame_set_in_samplerate(lame, 44100);
    lame_set_num_channels(lame, 2);
    //设置MP3的编码方式
    lame_set_VBR(lame, vbr_default);

    lame_init_params(lame);

    LOG_I("lame init finish");
    int read;
    int write; //代表读了多少个次 和写了多少次
    int total = 0; // 当前读的wav文件的byte数目
    do {
        read = fread(wav_buffer, sizeof(short int) * 2, 8192, fwav);
        if (read != 0) {
            write = lame_encode_buffer_interleaved(lame, wav_buffer, read, mp3_buffer, 8192);
            //把转化后的mp3数据写到文件里
            fwrite(mp3_buffer, sizeof(unsigned char), write, fmp3);
        }
        if (read == 0) {
            lame_encode_flush(lame, mp3_buffer, 8192);
        }

    } while (read != 0);
    LOG_I("convert  finish");
    lame_close(lame);
    fclose(fwav);
    fclose(fmp3);
}


extern "C" JNIEXPORT void JNICALL
Java_com_yc_lame_LameUtil_test2(JNIEnv *env, jclass obj, jstring jwav, jstring jmp3,
                                jint inSampleRate, jint inChannels, jint outSampleRate,
                                jint byteRate, jint mode, jint quality) {

    jboolean isCopy;
    const char *cwav = env->GetStringUTFChars(jwav, &isCopy);
    const char *cmp3 = env->GetStringUTFChars(jmp3, &isCopy);

    // 打开wav文件， "rb"打开一个二进制文件，文件必须存在，允许读写
    FILE *fwav = fopen(cwav, "rb");

    // 移除wav文件头
    fseek(fwav, 4 * 1024, SEEK_CUR);
    //新建一个二进制文件，已存在的文件将内容清空，允许读写
    FILE *fmp3 = fopen(cmp3, "wb+");

    int channel = inChannels;
    int BUFF_SIZE = 8192;
    short int wav_buffer[BUFF_SIZE * channel];
    unsigned char mp3_buffer[BUFF_SIZE];

    // init lame
    lame_global_flags *lameConvert;
    lameConvert = lame_init();

    lame_set_in_samplerate(lameConvert, inSampleRate);
    lame_set_num_channels(lameConvert, inChannels);
    lame_set_out_samplerate(lameConvert, outSampleRate);
    if (byteRate > 0) {
        lame_set_brate(lameConvert, byteRate);
    }
    lame_set_mode(lameConvert, (MPEG_mode) mode);
    lame_set_quality(lameConvert, quality);

    lame_set_VBR(lameConvert, vbr_default);
    lame_init_params(lameConvert);
    int read;
    int write;
    int total = 0;
    do {
        read = fread(wav_buffer, sizeof(short int) * channel, BUFF_SIZE, fwav);
        total += read * sizeof(short int) * channel;
        if (read != 0) {
            write = lame_encode_buffer(lameConvert, wav_buffer, nullptr, read, mp3_buffer,
                                       BUFF_SIZE);
        } else {
            write = lame_encode_flush(lameConvert, mp3_buffer, BUFF_SIZE);
        }
        fwrite(mp3_buffer, 1, write, fmp3);

    } while (read != 0);
    lame_mp3_tags_fid(lameConvert, fmp3);
    lame_close(lameConvert);
    fclose(fwav);
    fclose(fmp3);
}